package com.tang.portal.component.pay.impl;


import com.alibaba.fastjson2.JSON;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayResponse;
import com.alipay.api.domain.AlipayFundTransUniTransferModel;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.domain.Participant;
import com.alipay.api.request.*;
import com.tang.common.enums.AliPayType;
import com.tang.common.properties.AliPayConfigProperties;
import com.tang.common.properties.sys.CoolTeaProperties;
import com.tang.framework.core.cache.CoolTeaConfig;
import com.tang.common.exception.BusinessException;
import com.tang.common.exception.eumes.Error;
import com.tang.portal.component.pay.PayService;
import com.tang.portal.component.pay.model.ali.PayBizContent;
import com.tang.portal.component.pay.model.ali.RefundBizContent;
import com.tang.portal.component.pay.model.callback.CallBack;
import com.tang.portal.component.pay.model.create.req.AliCreatePay;
import com.tang.portal.component.pay.model.create.res.AliCreatePayResponse;
import com.tang.portal.component.pay.model.refund.req.AliRefund;
import com.tang.portal.component.pay.model.refund.res.AliRefundResponse;
import com.tang.portal.component.pay.model.withdraw.req.AliWithdraw;
import com.tang.portal.component.pay.model.withdraw.res.AliWithdrawResponse;
import lombok.SneakyThrows;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import jakarta.annotation.Resource;
import java.math.RoundingMode;

/**
 * 支付宝支付
 *
 * @author tang jun liang
 * @Date 2023/6/25 13:37
 */
@Component("aliPayService")
@ConditionalOnProperty(prefix = "cool-tea", name = "ali-pay", havingValue = "true")
public class AliPayServiceImpl implements PayService<AliCreatePay, AliCreatePayResponse, AliRefund, AliRefundResponse, AliWithdraw, AliWithdrawResponse, CallBack> {


    @Resource
    private CoolTeaProperties coolTeaProperties;

    @Resource
    private AlipayClient alipayClient;

    @SneakyThrows
    @Override
    public AliCreatePayResponse create(AliCreatePay aliCreatePay) {
        return new AliCreatePayResponse(doCreate(aliCreatePay));
    }

    @SneakyThrows
    private AlipayResponse doCreate(AliCreatePay aliCreatePay) {
        AliPayConfigProperties aliPayConfigProperties = CoolTeaConfig.getConfig(AliPayConfigProperties.class);
        if (aliCreatePay.getAliPayType().equals(AliPayType.APP)) {
            return doCreateApp(aliCreatePay, aliPayConfigProperties);
        } else if (aliCreatePay.getAliPayType().equals(AliPayType.PAGE) ) {
            return doCreatePage(aliCreatePay, aliPayConfigProperties);
        } else if (aliCreatePay.getAliPayType().equals(AliPayType.HUA_BEI)) {
            return doCreateHuaBei(aliCreatePay, aliPayConfigProperties);
        } else if (aliCreatePay.getAliPayType().equals(AliPayType.FACE_TO_FACE)) {
            return doCreateFaceToFace(aliCreatePay, aliPayConfigProperties);
        }else if (aliCreatePay.getAliPayType().equals(AliPayType.WAP)){
            return doCreateWap(aliCreatePay, aliPayConfigProperties);
        }
        else {
            throw new BusinessException(Error.UNKNOWN_PAY_METHOD);
        }
    }

    /**
     * 手机h5 支付
     * @param aliCreatePay
     * @param aliPayConfigProperties
     * @return
     */
    @SneakyThrows
    private AlipayResponse doCreateWap(AliCreatePay aliCreatePay, AliPayConfigProperties aliPayConfigProperties) {
        AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
        request.setBizContent(buildBizContent(aliCreatePay));
        request.setNotifyUrl(aliPayConfigProperties.getNotifyUrl());
        return alipayClient.sdkExecute(request);
    }

    /**
     * app支付
     * @param aliCreatePay
     * @param aliPayConfigProperties
     * @return
     */
    @SneakyThrows
    private AlipayResponse doCreateApp(AliCreatePay aliCreatePay, AliPayConfigProperties aliPayConfigProperties) {
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        request.setNotifyUrl(aliPayConfigProperties.getNotifyUrl());
        request.setReturnUrl(aliCreatePay.getReturnUrl());
        request.setBizContent(buildBizContent(aliCreatePay));
        return alipayClient.pageExecute(request);
    }

    /**
     * 花呗支付
     * @param aliCreatePay
     * @param aliPayConfigProperties
     * @return
     */
    @SneakyThrows
    private AlipayResponse doCreateHuaBei(AliCreatePay aliCreatePay, AliPayConfigProperties aliPayConfigProperties) {
        throw new BusinessException(Error.NOT_IMPLEMENTED);
    }

    /**
     * 面对面支付
     * @param aliCreatePay
     * @param aliPayConfigProperties
     * @return
     */
    @SneakyThrows
    private AlipayResponse doCreateFaceToFace(AliCreatePay aliCreatePay, AliPayConfigProperties aliPayConfigProperties) {
        throw new BusinessException(Error.NOT_IMPLEMENTED);
    }


    /**
     * pc网站支付
     * @param aliCreatePay
     * @param aliPayConfigProperties
     * @return
     */
    @SneakyThrows
    private AlipayResponse doCreatePage(AliCreatePay aliCreatePay, AliPayConfigProperties aliPayConfigProperties) {
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        request.setBizContent(buildBizContent(aliCreatePay));
        request.setNotifyUrl(aliPayConfigProperties.getNotifyUrl());
        return alipayClient.sdkExecute(request);
    }

    private String buildBizContent(AliCreatePay aliCreatePay) {
        PayBizContent payBizContent = PayBizContent.builder()
                .productCode(aliCreatePay.getProductCode())
                .subject(aliCreatePay.getInfo())
                .outTradeNo(aliCreatePay.getOrderNo())
                .totalAmount(aliCreatePay.getPayPrice()
                        .setScale(2, RoundingMode.UP).toString()).build();
        return JSON.toJSONString(payBizContent);
    }


    @SneakyThrows
    @Override
    public AliRefundResponse refund(AliRefund aliRefund) {
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        RefundBizContent refundBizContent = new RefundBizContent();
        refundBizContent.setTradeNo(aliRefund.getPayNo());
        refundBizContent.setOutRequestNo(aliRefund.getAfterSalesNo());
        refundBizContent.setRefundAmount(aliRefund.getAfterSalesPrice()
                .setScale(2, RoundingMode.UP).toString());
        request.setBizContent(JSON.toJSONString(refundBizContent));
        return new AliRefundResponse(alipayClient.execute(request));
    }

    @SneakyThrows
    @Override
    public AliWithdrawResponse withdraw(AliWithdraw withdraw) {
        AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
        AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
        model.setOutBizNo(withdraw.getWithdrawNo());
        model.setRemark(withdraw.getDesc());
        model.setBusinessParams("{\"payer_show_name_use_alias\":\"true\"}");
        model.setBizScene(withdraw.getBizScene());
        Participant payeeInfo = new Participant();
        payeeInfo.setIdentity(withdraw.getIdentity());
        payeeInfo.setIdentityType(withdraw.getIdentityType());
        payeeInfo.setName(withdraw.getName());
        model.setPayeeInfo(payeeInfo);
        model.setTransAmount(withdraw.getPrice().setScale(0, RoundingMode.UP).toString());
        model.setProductCode(withdraw.getProductCode());
        model.setOrderTitle(withdraw.getDesc());
        request.setBizModel(model);
        return new AliWithdrawResponse(alipayClient.certificateExecute(request));
    }

    @Override
    public void callBack(CallBack callBack) {

    }


}
